﻿using MathNet.Numerics.Statistics;
using System;
using System.Diagnostics;
using System.Linq;
using System.Windows.Automation.Peers;

namespace FilmBlowingMachine.PLC
{
    public struct MeasuringPoint
    {
        public float position;
        public ushort thickness;
        public uint angle;

    }
    public class DeltaAS200
    {
        private ushort controlWord;
        private bool homing;
        private ushort[] heatingPWM;
        private int homingFastFreq;
        private int homingLowFreq;
        private int autoFreq;
        private int pulsePerMill;

        public DeltaAS200(string ip, int port,ushort numberOfHeatingPoints)
        {
            modbus = new ModbusTCP(ip, port, 1);
            //NumberOfMeasuringPoints = numberOfMeasuringPoints;
            NumberOfHeatingPoints = numberOfHeatingPoints;
            HeatingPWM = new ushort[numberOfHeatingPoints];
            MeasuringPoints = new MeasuringPoint[NumberOfMeasuringPoints];
        }

        private ModbusTCP modbus { get; set; }
        public bool IsConnected { get => modbus.IsConnected;}
        public int NumberOfMeasuringPoints => (modbus.ReadDWord(0) / 5) + 1;
        public ushort NumberOfHeatingPoints { get; set; }
        public MeasuringPoint[] MeasuringPoints { get; set; }
        public float CylinderDiameter { get; set; }
        public float SlampingStartPosition { get; set; }
        public float SlampingEndPosition { get; set; }
        public int InitialHeatingNumber { get; set; }
        public float DistanceFromBlowingToMeasuring { get; set; }
        public float ConveyorSpeed { get; set; }
        public ushort ControlWord
        {
            get { return controlWord; }
            set {
                controlWord = value;
                modbus.WriteSingleWord(101, controlWord);
            }
        }
        public ushort StatusWord { get { return modbus.ReadSingleWord(100); } }
        public ushort[] HeatingPWM
        {
            get { return heatingPWM; }
            set {
                heatingPWM = value;
                modbus.WriteMultipleRegisters(300, heatingPWM); }
        }
        public bool Homing
        {
            get { return homing; }
            set {
                homing = value;
                modbus.WriteSingleCoil(10, homing); }
        }
        public bool HomingFlag { get; set; }
        public bool HomingFinished { get; set; }
        public int HomingFastFreq
        {
            get { return homingFastFreq; }
            set {
                homingFastFreq = value;
                modbus.WriteDWord(200, homingFastFreq); }
        }
        public int HomingLowFreq
        {
            get { return homingLowFreq; }
            set {
                homingLowFreq = value;
                modbus.WriteDWord(202, homingLowFreq); }
        }
        public int AutoFreq
        {
            get { return autoFreq; }
            set {
                autoFreq = value;
                modbus.WriteDWord(1000, autoFreq); }
        }
        public int PulsePerMill
        {
            get { return pulsePerMill; }
            set
            {
                pulsePerMill = value;
                modbus.WriteDWord(142, pulsePerMill);
            }
        }

        /// <summary>
        /// 连接PLC
        /// </summary>
        /// <returns>连接成功时，返回true；连接失败时，返回false</returns>
        public bool Connect()
        {
            return modbus.Connect();
        }

        /// <summary>
        /// 获取测量数据
        /// </summary>
        /// <returns>获取数据成功时，返回true；否则返回false</returns>
        public bool GetMeasuringPoints()
        {
            int regNum = 5;
            ushort[] buf = modbus.ReadHoldingRegisters(4000, (ushort)(NumberOfMeasuringPoints * regNum));

            if (buf == null) return false;
            for (int i = 0; i < NumberOfMeasuringPoints; i++)
            {
                int offset = i * regNum;
                MeasuringPoints[i].thickness = buf[offset];
                MeasuringPoints[i].angle = BitConverter.ToUInt32(BitConverter.GetBytes(buf[offset + 1] | (uint)(buf[offset + 2] << 16)));
                MeasuringPoints[i].position = BitConverter.ToSingle(BitConverter.GetBytes(buf[offset + 3] | (uint)(buf[offset + 4] << 16)));
            }
            return true;
        }

        /// <summary>
        /// 过滤从PLC获取的数据，转换成计算时所需要的数据
        /// </summary>
        /// <returns>构建矩阵所需要的数据</returns>
        private float[] FilterData()
        {
            return null;
        }

        /// <summary>
        /// 求解矩阵，返回120个加热点对应的厚度
        /// </summary>
        /// <returns></returns>
        public float[] ComputeFilmThickness()
        {
            float[] ans = new float[NumberOfMeasuringPoints];

            return ans;
        }

        public void ReadParamsFromPLC()
        {
            ControlWord = modbus.ReadSingleWord(101);
            Homing = modbus.ReadCoils(10, 1)[0];
            HeatingPWM = modbus.ReadHoldingRegisters(300, 120);
            HomingFastFreq = modbus.ReadDWord(200);
            HomingLowFreq = modbus.ReadDWord(202);
            AutoFreq = modbus.ReadDWord(1000);
            PulsePerMill = modbus.ReadDWord(142);
        }

        public void ReadParamsAlways()
        {
            HomingFlag = modbus.ReadCoils(11, 1)[0];
            HomingFinished = modbus.ReadCoils(15, 1)[0];
        }
    }
}
